package com.sky.service.impl;

import com.sky.entity.Orders;
import com.sky.mapper.OrdersMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.service.WorkSpaceService;
import com.sky.vo.*;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {
    @Autowired
    private OrdersMapper ordersMapper;
    // 默认金额
    private static final BigDecimal DEFAULT_MONEY = new BigDecimal("0.00");
    // 默认订单数
    private static final String DEFAULT_ORDER_COUNT = "0";
    // 默认用户数
    private static final String DEFAULT_USER_COUNT = "0";
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WorkSpaceService workSpaceService;

    @Override
    public TurnoverReportVO getTurnoverStatistics(LocalDate begin, LocalDate end) {
        // 1. 生成完整的日期范围列表
        List<LocalDate> dateRange = generateDateRange(begin, end);

        // 2. 查询数据库中有数据的日期和营业额
        Map<String, Object> map = new HashMap<>();
        map.put("begin", LocalDateTime.of(begin, LocalTime.MIN));
        map.put("end", LocalDateTime.of(end, LocalTime.MAX));
        map.put("status", Orders.COMPLETED);

        List<Map<String, Object>> turnoverStatisticsList = ordersMapper.countTurnoverStatistics(map);

        // 3. 将数据库结果转换为Map，便于查找
        Map<String, String> turnoverMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(turnoverStatisticsList)) {
            turnoverMap = turnoverStatisticsList.stream()
                    .collect(Collectors.toMap(
                            data -> data.get("everyday").toString(),
                            data -> {
                                String amount = data.get("totalAmount").toString();
                                return StringUtils.isNotBlank(amount) ? amount : DEFAULT_MONEY.toString();
                            }
                    ));
        }

        // 4. 为每个日期生成对应的营业额（没有数据的日期设为0.00）
        List<String> dateList = new ArrayList<>();
        List<String> turnoverList = new ArrayList<>();

        for (LocalDate date : dateRange) {
            String dateStr = date.toString();
            dateList.add(dateStr);
            turnoverList.add(turnoverMap.getOrDefault(dateStr, DEFAULT_MONEY.toString()));
        }

        // 5. 返回结果
        return TurnoverReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .turnoverList(StringUtils.join(turnoverList, ","))
                .build();
    }

    @Override
    public SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end) {
        // 创建map集合
        Map<String, Object> map = new HashMap<>();
        map.put("begin", LocalDateTime.of(begin, LocalTime.MIN));
        map.put("end", LocalDateTime.of(end, LocalTime.MAX));
        map.put("status", Orders.COMPLETED);
        // 查询指定时间区间内的销量排名top10数据
        List<Map<String, Object>> salesTop10 = ordersMapper.getSalesTop10(map);
        // 判断salesTop10是否为空
        if (CollectionUtils.isEmpty(salesTop10)) {
            // 为空
            return SalesTop10ReportVO.builder()
                    .nameList("")
                    .numberList("")
                    .build();
        }
        // 不为空封装响应数据
        String nameList = salesTop10.stream().map(nameMap -> nameMap.get("name").toString()).collect(Collectors.joining(","));
        String numberList = salesTop10.stream().map(numberMap -> numberMap.get("totalSales").toString()).collect(Collectors.joining(","));
        return SalesTop10ReportVO.builder()
                .nameList(nameList)
                .numberList(numberList)
                .build();
    }

    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        // 1.根据时间范围获取完整日期列表
        List<LocalDate> dateList = generateDateRange(begin, end);
        // 创建map集合
        Map<String, Object> map = new HashMap<>();
        map.put("begin", LocalDateTime.of(begin, LocalTime.MIN));
        map.put("end", LocalDateTime.of(end, LocalTime.MAX));
        List<Map<String, Object>> countOrderStatistics = ordersMapper.countOrderStatistics(map);
        // 2.获取每日订单数
        List<Integer> orderCountList = new ArrayList<>();
        // 将数据库结果转换为Map
        Map<String, String> countOrderStatisticsMap = countOrderStatisticsToMap(countOrderStatistics);
        // (判断)为每个日期生成对应的订单数(没有数据的日期设为0)
        for (LocalDate date : dateList) {
            String dateStr = date.toString();
            orderCountList.add(Integer.parseInt(countOrderStatisticsMap.getOrDefault(dateStr, DEFAULT_ORDER_COUNT)));
        }
        // 3.获取时间区间内的总订单数量
        int totalOrderCount = orderCountList.stream().mapToInt(Integer::intValue).sum();


        // 4.获取时间区间内每日有效订单数
        map.put("status", Orders.COMPLETED);
        List<Map<String, Object>> validCountOrderStatistics = ordersMapper.countOrderStatistics(map);
        // 创建一个List<Integer>用于存放 每日有效订单数
        List<Integer> validOrderCountList = new ArrayList<>();
        // 将数据库结果转换为Map
        Map<String, String> validCountOrderStatisticsMap = countOrderStatisticsToMap(validCountOrderStatistics);
        // (判断)为每个日期生成对应的有效订单数(没有数据的日期设为0)
        for (LocalDate date : dateList){
            String dateStr = date.toString();
            validOrderCountList.add(Integer.parseInt(validCountOrderStatisticsMap.getOrDefault(dateStr,DEFAULT_ORDER_COUNT)));
        }
        // 5.获取时间区间内的有效订单总数量
        Integer validOrderCount = validOrderCountList.stream().reduce(0, Integer::sum);
        // 6.计算订单完成率
        double orderCompletionRate = 0.0;
        if (totalOrderCount != 0) {
            orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount;
        }

        return OrderReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .orderCountList(StringUtils.join(orderCountList, ","))
                .validOrderCountList(StringUtils.join(validOrderCountList, ","))
                .totalOrderCount(totalOrderCount)
                .validOrderCount(validOrderCount)
                .orderCompletionRate(orderCompletionRate)
                .build();
    }
    /**
     * 将订单统计数据库结果转换为Map，便于查找
     * @param countOrderStatistics
     * @return
     */
    private Map<String,String> countOrderStatisticsToMap(List<Map<String, Object>> countOrderStatistics){
        Map<String, String> countOrderStatisticsMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(countOrderStatistics)) {
            countOrderStatisticsMap = countOrderStatistics.stream()
                    .collect(Collectors.toMap(
                                    data -> data.get("everyday").toString(),
                                    data -> data.get("orderCount").toString()
                            )
                    );
        }
        return countOrderStatisticsMap;
    }
    @Override
    public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
        // 1. 生成完整的日期范围列表
        List<LocalDate> dateList = generateDateRange(begin, end);

        // 2. 查询新增用户数据（按日期范围查询，按日期分组）
        Map<String, Object> newUserMap = new HashMap<>();
        newUserMap.put("begin", LocalDateTime.of(begin, LocalTime.MIN));
        newUserMap.put("end", LocalDateTime.of(end, LocalTime.MAX));
        List<Map<String, Object>> newCountUserStatistics = userMapper.countUserStatistics(newUserMap);

        // 3. 将新增用户数据转换为Map，便于查找
        Map<String, String> newCountUserMap = countUserListToMap(newCountUserStatistics);

        // 4. 为每个日期生成对应的新增用户数和总用户数
        List<String> newUserList = new ArrayList<>();
        List<String> totalUserList = new ArrayList<>();

        for (LocalDate date : dateList) {
            String dateStr = date.toString();

            // 新增用户数：从Map中获取，没有则为0
            newUserList.add(newCountUserMap.getOrDefault(dateStr, DEFAULT_USER_COUNT));

            // 总用户数：查询截止到当前日期的累计用户数
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            Map<String, Object> totalUserQuery = new HashMap<>();
            totalUserQuery.put("end", endTime);
            List<Map<String, Object>> totalUserResult = userMapper.countUserStatistics(totalUserQuery);

            // 计算截止到当前日期的总用户数
            int totalCount = totalUserResult.stream()
                    .mapToInt(data -> Integer.parseInt(data.get("totalUser").toString()))
                    .sum();
            totalUserList.add(String.valueOf(totalCount));
        }

        // 5. 返回结果
        return UserReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .totalUserList(StringUtils.join(totalUserList, ","))
                .newUserList(StringUtils.join(newUserList, ","))
                .build();
    }

    @Override
    public void exportBusinessData(HttpServletResponse response) {
        //1.查询数据库，获取营业数据--查询最近30天的数据
        LocalDate dateBegin = LocalDate.now().minusDays(30);
        LocalDate dateEnd = LocalDate.now().minusDays(1);
        // 查询概览数据
        BusinessDataVO businessDataVO = workSpaceService.getBusinessData(LocalDateTime.of(dateBegin, LocalTime.MIN), LocalDateTime.of(dateEnd, LocalTime.MAX));
        //2.通过POI将数据写入到Excel文件中
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");

        try {
            // 检查资源是否存在
            if (is == null) {
                throw new RuntimeException("模板文件未找到: template/运营数据报表模板.xlsx");
            }
            //基于模版文件创建的新一个的Excel文件
            XSSFWorkbook excel = new XSSFWorkbook(is);
            //获取文件表格的Sheet页
            XSSFSheet sheet = excel.getSheet("Sheet1");
            //填充数据 -- 时间
            sheet.getRow(1).getCell(1).setCellValue("时间："+dateBegin+"至"+dateEnd);
            // 获得第四行
            XSSFRow row = sheet.getRow(3);
            row.getCell(2).setCellValue(businessDataVO.getTurnover());
            row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
            row.getCell(6).setCellValue(businessDataVO.getNewUsers());
            //获得第五航
            row = sheet.getRow(4);
            row.getCell(2).setCellValue(businessDataVO.getValidOrderCount());
            row.getCell(4).setCellValue(businessDataVO.getUnitPrice());

            // 填充明细数据 - 先填充数据再写入输出流
            for (int i = 0; i < 30; i++) {
                LocalDate date = dateBegin.plusDays(i);
                //查询某一天的营业数据
                BusinessDataVO businessData = workSpaceService.getBusinessData(LocalDateTime.of(date, LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX));

                // 添加调试日志
                log.info("填充明细数据 - 日期: {}, 营业额: {}, 有效订单: {}, 完成率: {}, 客单价: {}, 新用户: {}",
                    date, businessData.getTurnover(), businessData.getValidOrderCount(),
                    businessData.getOrderCompletionRate(), businessData.getUnitPrice(), businessData.getNewUsers());

                //获得某一行
                row = sheet.getRow(7+i);

                // 安全地设置单元格值，处理空值情况
                row.getCell(1).setCellValue(date.toString());
                row.getCell(2).setCellValue(businessData.getTurnover() != null ? businessData.getTurnover() : 0.0);
                row.getCell(3).setCellValue(businessData.getValidOrderCount() != null ? businessData.getValidOrderCount() : 0);
                row.getCell(4).setCellValue(businessData.getOrderCompletionRate() != null ? businessData.getOrderCompletionRate() : 0.0);
                row.getCell(5).setCellValue(businessData.getUnitPrice() != null ? businessData.getUnitPrice() : 0.0);
                row.getCell(6).setCellValue(businessData.getNewUsers() != null ? businessData.getNewUsers() : 0);
            }

            //3.通过输出流将Excel文件下载到客户端浏览器
            ServletOutputStream outputStream = response.getOutputStream();
            excel.write(outputStream);

            //关闭资源
            outputStream.close();
            excel.close();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    private Map<String, String> countUserListToMap(List<Map<String, Object>> countUserStatistics) {
        Map<String, String> countUserStatisticsMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(countUserStatistics)){
            countUserStatisticsMap = countUserStatistics.stream().collect(Collectors.toMap(
                    data -> data.get("everyday").toString(),
                    data -> data.get("totalUser").toString()
            ));
        }
        return countUserStatisticsMap;
    }

    /**
     * 生成日期范围列表（包含起始和结束日期）
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return 日期列表
     */
    private List<LocalDate> generateDateRange(LocalDate begin, LocalDate end) {
        List<LocalDate> dateList = new ArrayList<>();
        LocalDate current = begin;
        // 包含结束日期
        while (!current.isAfter(end)) {
            dateList.add(current);
            current = current.plusDays(1);
        }

        return dateList;
    }

}
